<template>
  <div class="container">
    <div class="left">
      <div style="height: 50px; line-height: 50px; padding: 0 20px;">
        <label>监控设备列表</label>
      </div>
      <div class="camera-list">
        <el-input v-model="filterCameraText" placeholder="请输入设备名称" :suffix-icon="Search" style="width: 238px; margin-bottom: 18px; " @input="queryCamera" />

        <el-checkbox-group id="camera-checkbox-group" ref="cameraCheckboxGroup" v-model="checkedCameraIdList" >
          <el-tree-v2
            ref="cameraTreeRef"
            v-loading="cameraTreeLoading"
            style="width: 100%; height: 100%"
            :height="treeHeight"
            :data="cameraTreeData"
            node-key="nodeId" 
            :props="{ value: 'nodeId', label: 'nodeName', children: 'children' }"
            :filter-method="filterCamera"
          >
            <template #default="{ node, data }">
              <template v-if="data.equipmentCameraGroupId">
                <svg-icon icon-class="camera-circle" style="font-size: 18px; position: relative; right: 7px;;" />
                <span style="display: inline-block; width: calc(100% - 90px); height: 26px; line-height: 26px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" >
                  {{ data.nodeName }} 
                </span>
              </template>
              <el-checkbox v-else :value="data.nodeId" :disabled="data.deviceStatus=='OFFLINE'" @change="(flag)=> { cameraCheckChange(data.nodeId, flag) }"> 
                <span v-if="data.deviceStatus=='OFFLINE'" style="color: rgb(200 90 90);">（离线）</span> 
                <span>{{ node.label }}</span>
              </el-checkbox>
            </template>
          </el-tree-v2>
        </el-checkbox-group>
      </div>
    </div>
    <div id="right" class="right">
      视频地址：{{ videoUrl }}
        <div class="video_player">
          <video id="videoElement" controls width="640" height="360"></video>
          <div class="menu">
            <div class="play" @click="togglePlay">{{ isPlaying ? '暂停' : '播放' }}</div>
            <div class="time">{{ currentTime }}</div>
            <div class="progress_bar">
              <div :style="{ width: progressBarWidth + '%' }"></div>
              <i :style="{ left: progressBarWidth + '%' }"></i>
            </div>
            <div class="speed">
              <!-- 倍速按钮 -->
              <div class="speed-button" @click="toggleSpeedMenu">
                倍速
              </div>
              <!-- 显示倍速选项的列表 -->
              <ul v-if="isSpeedMenuVisible" class="speed-options">
                <li v-for="speed in speedOptions" :key="speed" @click="setSpeed(speed)">
                  {{ speed }}x
                </li>
              </ul>
            </div>
            <div v-click-outside="hideVolumeController" class="volume">
              <span @click="toggleVolumeController">音量</span>
              <div v-if="volumeControllerVisible" class="Controller" @mousedown="startAdjustVolume">
                <div class="volume-bar">
                  <div
                    class="volume-fill"
                    :style="{ height: volume * 100 + '%' }"
                  ></div>
                  <div
                    class="volume-handle"
                    :style="{ bottom: volume * 100 + '%' }"
                  ></div>
                </div>
              </div>
            </div>
            <div class="screenshot" @click="takeScreenshot">截图</div>
            <div class="full" @click="toggleFullscreen">全屏</div>
          </div>
        </div>
        <!-- <div class="input-container">
          <label for="videoURL">Enter FLV URL:</label>
          <input type="text" id="videoURL" v-model="videoURL" placeholder="http://your-server-path/video.flv" size="50" />
          <button @click="loadVideo">Load Video</button>
        </div> -->
    </div>
  </div>
</template>

<script setup name="realTimeMonitor" lang="ts">
import request from '@/utils/request';
import { Calendar, Search } from '@element-plus/icons-vue'
import type { TreeNodeData } from 'element-plus/es/components/tree-v2/src/types'

import { ClickOutside as vClickOutside } from 'element-plus';
import flvjs from 'flv-h265.js';

const { proxy } = getCurrentInstance() as ComponentInternalInstance;

const filterCameraText = ref();
const leftDomHeight = ref();
const cameraTreeRef = ref<any>()
const cameraTreeLoading = ref(false)
    interface Tree{ label: string, children?: Tree[] }
const treeHeight = ref(0)

const videoURL = ref('');
const flvPlayer = ref(null);
const isPlaying = ref(false);
const currentTime = ref('0:00');
const duration = ref('0:00');
const progressBarWidth = ref(0);
const selectedSpeed = ref('1.0');
const isSpeedMenuVisible = ref(false);
const speedOptions = ['0.5', '1.0', '1.5', '1.25', '2.0'];
const volumeControllerVisible = ref(false);
const volume = ref(1.0);
const isAdjusting = ref(false);

/**
     * 查询摄像头信息列表
     * */
const cameraTreeData = ref([]);
const cameraCheckboxGroup = ref();
const getCameraTreeList = async () => {
  cameraTreeLoading.value = true
  let cameraTreeRes = await request({
    url: '/equipment/equipment-camera-group/tree',
    method: 'get'
  }).finally(() => { cameraTreeLoading.value = false })

  console.log('获取摄像机：', cameraTreeRes)

  cameraTreeData.value = cameraTreeRes.data;

  //  展开所有节点
  nextTick(()=> {
    cameraTreeRef.value.setExpandedKeys(cameraTreeData.value.map(item=> { return item.nodeId }));
  })
}

/**
     * 过滤摄像头
     */
const queryCamera = (query: string) => {
      cameraTreeRef.value!.filter(query)
}

/**
     * 过滤摄像头
     */
const filterCamera = (query: string, data: TreeNodeData) => {
  return data.nodeName!.includes(query)
}

/**
     * 摄像机复选框点击
     */
const checkedCameraIdList = ref([]);
let videoUrl = ref<any>()
const cameraCheckChange = (cameraId: any, flag: any) => {
  console.log('点击的摄像机：', cameraId, flag)

  proxy.$modal.loading('加载中')
  request({
    url: '/equipment/equipment-info/get-video-url/' + cameraId,
    method: 'get',
    params: { playType: 0, playProtocol: 0 }
  }).then((videoRes)=> {
    console.log('获取视频地址：', videoRes)
    if (videoRes.data && videoRes.data.media_url) {
      // videoUrl.value = JSON.parse(videoRes.data.media_url).wan
      const url = JSON.parse(videoRes.data.media_url).wan;
      videoUrl.value = url; // 将获取的 URL 保存在 videoUrl 中
      loadVideo(url); // 获取 URL 后立即调用 loadVideo 播放视频
    }
  }).finally(()=> { proxy.$modal.closeLoading() })
}

onMounted(async () => {
  //  获取左侧元素高度
  const leftElement = document.getElementById('right');
  leftDomHeight.value = leftElement.clientHeight

  // 设置树高度
  const cameraCheckboxGroupElement = document.getElementById('camera-checkbox-group');
  treeHeight.value = cameraCheckboxGroupElement.clientHeight

  //  获取摄像机
  await getCameraTreeList();
});

// 使用flv播放器
// const loadVideo = (url: string) => {
//   if (flvjs.isSupported() && url) {
//     if (flvPlayer.value) {
//       flvPlayer.value.unload();
//       flvPlayer.value.detachMediaElement();
//       flvPlayer.value.destroy();
//     }
//     const videoElement = document.getElementById("videoElement") as HTMLVideoElement;
//     flvPlayer.value = flvjs.createPlayer({
//       type: "flv",
//       url: url,
//     });
//     flvPlayer.value.attachMediaElement(videoElement);
//     flvPlayer.value.load();
//     flvPlayer.value.play();
//     videoElement.volume = volume.value;
//     isPlaying.value = true;
//   } else {
//     alert("视频地址无效或您的浏览器不支持播放 FLV 格式！");
//   }
// };

// 使用flv播放器增加H264 or H265判断
// const loadVideo = (url: string) => {
//   try {
//     if (flvjs.isSupported() && url) {
//       if (flvPlayer.value) {
//         flvPlayer.value.unload();
//         flvPlayer.value.detachMediaElement();
//         flvPlayer.value.destroy();
//       }

//       const videoElement = document.getElementById("videoElement") as HTMLVideoElement;
//       flvPlayer.value = flvjs.createPlayer({
//         type: "flv",
//         url: url,
//       });

//       // 判断流格式（例如根据文件扩展名或 MIME 类型）
//       if (url.endsWith('.m3u8') || url.includes('hls')) {
//         // HLS 流，通常是 H.264 或 H.265，可以自动处理
//         flvPlayer.value.attachMediaElement(videoElement);
//         flvPlayer.value.load();
//         flvPlayer.value.play();
//       } else{
//         // FLV 流，判断是否是 H.265 或 H.264
//         const hls = new Hls();
//         const isHEVC = false;
//         hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
//           // 判断流的编码类型，可以通过 data.manifest.parserTags 来识别编码格式
//           if (data.manifest.parserTags.some(tag => tag.codec === 'hevc')) {
//             isHEVC = true;
//           } else {
//             isHEVC = false;
//           }
//         });

//         if (isHEVC) {
//           flvPlayer.value = flvjs.createPlayer({
//             type: "flv",
//             url: url,
//             flvjs: {
//               mediaDataSource: {
//                 isLive: false,
//                 cors: true,
//                 withCredentials: false,
//                 h265: true, // 如果是 H.265
//               }
//             }
//           });
//         } else {
//           flvPlayer.value = flvjs.createPlayer({
//             type: "flv",
//             url: url,
//             flvjs: {
//               mediaDataSource: {
//                 isLive: false,
//                 cors: true,
//                 withCredentials: false,
//                 h265: false, // H.264
//               }
//             }
//           });
//         }
//         flvPlayer.value.attachMediaElement(videoElement);
//         flvPlayer.value.load();
//         flvPlayer.value.play();
//       }

//       videoElement.volume = volume.value;
//       isPlaying.value = true;
//     } else {
//       alert("视频地址无效或您的浏览器不支持播放 FLV 格式！");
//     }
//   } catch (error) {
//     console.error("播放失败:", error);
//     alert("无法播放视频，请稍后再试！");
//   }
// };

// 使用videojs播放器
const loadVideo = (url) => {
  try {
    // 销毁已有的播放器实例
    if (window.videoPlayer) {
      window.videoPlayer.dispose(); // 销毁现有播放器
    }

    // 获取视频元素
    const videoElement = document.getElementById('videoElement');

    // 确保视频元素存在
    if (!videoElement) {
      console.error('视频元素未找到！');
      alert('视频元素未找到！');
      return;
    }

    // 初始化 Video.js 播放器
    window.videoPlayer = videojs(videoElement, {
      autoplay: false,
      controls: true,
      techOrder: ['flvjs', 'html5'], // 优先使用 FLV.js 播放器
      sources: [{
        src: url,
        type: 'video/x-flv' // FLV 格式
      }]
    });

    // 播放器准备好后，开始播放
    window.videoPlayer.ready(() => {
      console.log('播放器已准备好，开始播放视频。');
      window.videoPlayer.play().catch((error) => {
        console.error('播放失败:', error);
        alert('无法播放视频，请稍后再试！');
      });
    });

    // 错误处理
    window.videoPlayer.on('error', () => {
      console.error('Video.js 播放错误:', window.videoPlayer.error());
      alert('播放失败，请检查视频地址是否正确！');
    });
  } catch (error) {
    console.error('加载视频失败:', error);
    alert('加载视频失败，请稍后再试！');
  }
};

const togglePlay = () => {
  const video = document.getElementById('videoElement') as HTMLVideoElement;
  if (video.paused) {
    video.play();
    isPlaying.value = true;
  } else {
    video.pause();
    isPlaying.value = false;
  }
};

const setSpeed = (speed: string) => {
  selectedSpeed.value = speed;
  isSpeedMenuVisible.value = false;
};

const toggleSpeedMenu = () => {
  isSpeedMenuVisible.value = !isSpeedMenuVisible.value;
};

const takeScreenshot = () => {
  const video = document.getElementById('videoElement') as HTMLVideoElement;
  const canvas = document.createElement('canvas');
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
  const ctx = canvas.getContext('2d');
      ctx!.drawImage(video, 0, 0, canvas.width, canvas.height);
      const imageURL = canvas.toDataURL('image/png');
      const link = document.createElement('a');
      link.href = imageURL;
      link.download = 'screenshot.png';
      link.click();
};

const toggleVolumeController = () => {
  volumeControllerVisible.value = !volumeControllerVisible.value;
};

// 开始调整音量
const startAdjustVolume = (event: MouseEvent) => {
  isAdjusting.value = true;
  adjustVolume(event);

  // 添加全局监听，便于拖动结束时取消监听
  document.addEventListener('mousemove', adjustVolume);
  document.addEventListener('mouseup', stopAdjustVolume);
};

// 调节音量
const adjustVolume = (event: MouseEvent) => {
  if (!isAdjusting.value) { return; }

  const volumeBar = event.currentTarget as HTMLElement;
  const rect = volumeBar.getBoundingClientRect();
  const offsetY = event.clientY - rect.top;
  const height = rect.height;
  const newVolume = Math.max(0, Math.min(1, 1 - offsetY / height)); // 计算音量比例
  volume.value = newVolume;

  const video = document.getElementById('videoElement') as HTMLVideoElement; // 获取视频元素
  if (video) { video.volume = volume.value; } // 设置音量
};

// 停止调整音量
const stopAdjustVolume = () => {
  isAdjusting.value = false;
  // 移除全局监听
  document.removeEventListener('mousemove', adjustVolume);
  document.removeEventListener('mouseup', stopAdjustVolume);
  volumeControllerVisible.value = false;
};

// 点击外部时隐藏音量控制器
const hideVolumeController = () => {
  volumeControllerVisible.value = false;
};

// 切换全屏
const toggleFullscreen = () => {
  const videoPlayer = document.querySelector('.video_player') as HTMLElement;
  if (document.fullscreenElement) {
    document.exitFullscreen();
  } else {
    videoPlayer.requestFullscreen();
  }
};

</script>

<style lang="scss" scoped>
* {
    padding: 0;
    margin: 0;
}
#videoElement::-webkit-media-controls {
    display: none !important;
}
#videoElement::-moz-media-controls {
    display: none !important;
}
#videoElement::-ms-media-controls {
    display: none !important;
}
.video_player {
            position: relative;
            width: 1000px;
            height: 500px;
            margin: 0 auto;
            overflow: hidden;
        }

        .video_player video {
            width: 100%;
            height: 100%;
        }

        .video_player .menu {
            position: absolute;
            width: 100%;
            height: 50px;
            background-color: rgba(0, 0, 0, 0.5);
            bottom: 0;
            left: 0;
        }

        .video_player .menu .play {
            position: absolute;
            width: 50px;
            height: 30px;
            border: 1px solid white;
            border-radius: 10px;
            color: white;
            text-align: center;
            line-height: 30px;
            top: 50%;
            left: 30px;
            transform: translateY(-50%);
            cursor: pointer;
        }
        .video_player .menu .screenshot {
            position: absolute; /* 确保定位是相对于父级的 .menu */
            width: 80px;
            height: 30px;
            border: 1px solid white;
            border-radius: 10px;
            color: white;
            text-align: center;
            line-height: 30px;
            top: 50%; /* 垂直居中 */
            left: 200px; /* 调整到合适的水平位置，可以根据需求修改 */
            transform: translateY(-50%); /* 垂直居中修正 */
            cursor: pointer;
        }
        .video_player .menu .screenshot:hover{
            background-color: rgb(219, 74, 74);
        }

        .video_player .menu .play:hover {
            background-color: rgb(219, 74, 74);
        }

        .time {
            position: absolute;
            width: 100px;
            height: 30px;
            color: white;
            text-align: center;
            line-height: 30px;
            top: 50%;
            left: 100px;
            transform: translateY(-50%);
        }

        /* 进度条 */
        .progress_bar {
            position: absolute;
            top: -6px;
            left: 0;
            width: 100%;
            height: 6px;
            background-color: #ccc;
            transition: height .2s linear, top .2s linear;
        }

        .progress_bar>div {
            width: 0px;
            height: 100%;
            background-color: rgb(250, 139, 12);
        }

        .progress_bar>i {
            position: absolute;
            top: -2px;
            left: 0px;
            transform: translateX(-50%);
            width: 10px;
            height: 10px;
            background-color: red;
            border-radius: 20px;
            transition: height .2s linear, top .2s linear, width .2s linear;
        }

        /* 倍数 */
        li {
            list-style: none;
        }

        .speed {
            position: absolute;
            top: 50%;
            right: 150px;
            transform: translateY(-50%);
            color: white;
            text-align: center;
            line-height: 30px;
        }

        .speed-options {
          position: absolute;
          top: -200px;  /* 根据需求调整位置 */
          left: 0;
          padding: 0;
          margin: 0;
          list-style: none;
          background-color: rgba(0, 0, 0, 0.7);
          border-radius: 5px;
          width: 80px;
          z-index: 10;  /* 确保显示在其他内容之上 */
          display: block;
        }

        .speed-options li {
          padding: 5px;
          cursor: pointer;
          color: white;
        }

        .speed-options li:hover {
          background-color: rgb(219, 74, 74);
        }

        .speed div {
            width: 50px;
            height: 30px;
            border: 1px solid white;
            border-radius: 10px;
            cursor: pointer;
        }
        .speed div:hover {
          background-color: rgb(219, 74, 74);
        }

        /* 音量 */
        .volume {
          position: absolute;
          top: 50%;
          right: 80px;
          transform: translateY(-50%);
          color: white;
          text-align: center;
          line-height: 30px;
        }

        .volume > span {
          display: block;
          width: 50px;
          height: 30px;
          border: 1px solid white;
          border-radius: 10px;
          cursor: pointer;
        }

        .volume > span:hover {
          background-color: rgb(219, 74, 74);
        }

        .Controller {
          position: absolute;
          top: -170px;
          width: 50px; /* 控制器的整体宽度 */
          height: 150px;
          border-radius: 10px;
          background-color: rgba(0, 0, 0, 0.5);
          display: flex; /* 启用弹性布局 */
          justify-content: center; /* 水平居中 */
          align-items: flex-end; /* 垂直底部对齐 */
        }

        .volume-bar {
          position: relative;
          width: 6px;
          height: 90%;
          background-color: rgba(255, 255, 255, 0.3); /* 背景色提升对比度 */
          border-radius: 5px;
          margin-bottom: 10%; /* 下空当 */
        }

        .volume-fill {
          position: absolute;
          width: 100%;
          background-color: rgb(250, 139, 12);
          bottom: 0;
          border-radius: 5px; /* 圆角效果 */
        }

        .volume-handle {
          position: absolute;
          width: 10px;
          height: 10px;
          background-color: white;
          border-radius: 50%;
          transform: translateX(-50%);
          left: 50%;
        }
/* 全屏 */
        .full {
            position: absolute;
            width: 50px;
            height: 30px;
            border: 1px solid white;
            border-radius: 10px;
            color: white;
            text-align: center;
            line-height: 30px;
            top: 50%;
            right: 10px;
            transform: translateY(-50%);
            cursor: pointer;
        }
        .input-container {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          margin: 20px auto;
          text-align: center;
        }

        .input-container label {
          margin-bottom: 10px;
        }

        .input-container input {
          margin-bottom: 10px;
          padding: 8px;
          width: 300px;
          box-sizing: border-box;
        }

        .input-container button {
          padding: 8px 16px;
          cursor: pointer;
          border-radius: 5px;
          background-color: #007BFF;
          color: white;
          border: none;
        }

        .input-container button:hover {
          background-color: #0056b3;
        }
        
    :deep(.el-card__header) {
        height: 60px;
    }
    :deep(.el-card__body) {
        height: calc(100% - 60px);
    }
    :deep(.pagination-container) {
        margin-top: 0;
    }
    :deep(.camera-scene-tabs .el-tabs__nav-scroll) {
      display: flex;
      justify-content: center;
    }
    :deep(.camera-scene-tabs > .el-tabs__content) {
      padding: 32px;
    }
    .container {
      display: flex;
      flex-direction: row !important;
      position: relative;
    }
    .left {
      height: 100%;
      width: 260px;
      position: absolute;
      left: 0;
      border: 1px solid #DCDFE6;
    }
    .right {
      height: 100%;
      width: calc(100% - 270px);
      border: 1px solid #DCDFE6;
      position: absolute;
      right: 0;
    }
    .camera-list {
      height: calc(100% - 50px);
      padding: 0 10px;
      display: flex;
      flex-direction: column;
    }
    .camera-control {
      height: 200px;
      display: flex;
      flex-wrap: wrap;
      justify-content: space-around;
      align-items: center;
      border: 1px solid #0b0a0a;
    }
    .camera-layout-item {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 40px;
      height: 40px;
      cursor: pointer;
    }
     .vue-grid-layout {
       height: calc(100% - 50px) !important;
       background: #ffffff;
       .vue-grid-item {
         display: flex;
         justify-content: center;
         align-items: center;
         background-color: #ccc;
         border: 1px solid #ccc;
       }
     }

    .vue-grid-item:not(.vue-grid-placeholder) {
      background: #eeecec;
      border: 1px solid #ccc;
    }

    .vue-grid-item .resizing {
      opacity: 0.9;
    }

    .vue-grid-item .static {
      background: #cce;
    }
    .vue-grid-item .text {
      font-size: 24px;
      text-align: center;
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      margin: auto;
      height: 100%;
      width: 100%;
    }
    .vue-grid-item .no-drag {
      height: 100%;
      width: 100%;
    }
    .vue-grid-item .minMax {
      font-size: 12px;
    }
    .vue-grid-item .add {
      cursor: pointer;
    }
    .vue-draggable-handle {
      position: absolute;
      width: 20px;
      height: 20px;
      top: 0;
      left: 0;
      background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><circle cx='5' cy='5' r='5' fill='#999999'/></svg>") no-repeat;
      background-position: bottom right;
      padding: 0 8px 8px 0;
      background-repeat: no-repeat;
      background-origin: content-box;
      box-sizing: border-box;
      cursor: pointer;
    }
    :deep(.el-tree-node__expand-icon) {
      left: 200px;
      font-size: 14px;
      color: #3c3c3c;
      transform: rotate(180deg);
    }
    :deep(.el-tree-node__expand-icon.expanded) {
      transform: rotate(90deg);
    }
    :deep(#camera-checkbox-group) {
      flex: 1;
    }
    :deep(#camera-checkbox-group .el-checkbox__inner) {
      border-radius: 50%;
    }
</style>
